package com.pzsh.jwt;

import com.pzsh.entity.ResponseWrapper;
import com.pzsh.enums.ErrorCodeEnum;
import com.pzsh.exception.ApiException;
import com.pzsh.redis.IRedisService;
import com.pzsh.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;

/**
 * 复制请求数据包body
 * 以提供 拦截器下 可数次获取Body数据包
 */
public class RepeatedlyReadFilter implements Filter {
    @Autowired
    private ITokenManager tokenManager;

    @Override
    public void init(FilterConfig fConfig) {
        ServletContext sc = fConfig.getServletContext();
        WebApplicationContext cxt = WebApplicationContextUtils.getWebApplicationContext(sc);

        if (cxt != null && cxt.getBean("redisTokenManager") != null && tokenManager == null) {
            tokenManager = (ITokenManager) cxt.getBean("redisTokenManager");
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        if (null == req || StringUtils.isNullStr(req.getContentType()) || req.getRequestURI().contains("swagger") || req.getRequestURI().contains("upload") || !req.getContentType().contains("application/json")) {
            chain.doFilter(request, response);
        } else {
            String servletPath = req.getServletPath();
            if (servletPath.contains("import") || servletPath.contains("/wechat/")) {
                chain.doFilter(request, response);
            } else {
                JSON json = this.getJSONObject(req);
                if (null == json) {
                    this.respFail(response);
                    return;
                }
                if (json instanceof JSONArray) {
                    ServletRequest requestWrapper = new RepeatedlyReadRequestWrapper(req, json.toString());
                    chain.doFilter(requestWrapper, response);
                }else {
                    JSONObject jsonObject = JSONObject.parseObject(json.toJSONString());
                    String token = jsonObject.getString("token");
                    if (StringUtils.isBlank(token)) {
                        token = req.getHeader("token");
                    }
                    if (StringUtils.isNotBlank(token)) {
                        //从token解析account
                        try {
                            String account = this.checkUserToken(token);
                            jsonObject.put("account", account);
                        } catch (ApiException e) {
                            this.tokenRespFail(response, e.getCode());
                            return;
                        }
                    }
                    ServletRequest requestWrapper = new RepeatedlyReadRequestWrapper(req, jsonObject.toString());
                    chain.doFilter(requestWrapper, response);
                }

            }
        }
    }

    private JSON getJSONObject(HttpServletRequest req) {
        String str = null, retStr = "";
        try {
            BufferedReader br = req.getReader();
            while ((str = br.readLine()) != null) {
                retStr += str;
            }
            if (StringUtils.isNotBlank(retStr)) {
                JSONObject jsonObject = JSONObject.parseObject(retStr);
                if (null == jsonObject) {
                    JSONArray.parseArray(retStr);
                }
                return jsonObject;
            }
        } catch (Exception e) {
            try {
                return JSONArray.parseArray(retStr);
            } catch (Exception ex) {
                return null;
            }
        }
        return null;
    }

    private JSONArray getJSONArray(HttpServletRequest req) {
        try {
            BufferedReader br = req.getReader();
            String str = null, retStr = "";
            while ((str = br.readLine()) != null) {
                retStr += str;
            }
            if (StringUtils.isNotBlank(retStr)) {
                JSONArray jsonObject = JSONArray.parseArray(retStr);
                return jsonObject;
            }
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 返回失败结果Json数据
     */
    private void respFail(ServletResponse response) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(JSON.toJSONString(ResponseWrapper.failed(ErrorCodeEnum.SW100)));
    }

    private void tokenRespFail(ServletResponse response, int code) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(JSON.toJSONString(ResponseWrapper.failed(ErrorCodeEnum.getEnum(code))));
    }

    /**
     * 用户参数绑定
     */
    public String checkUserToken(String token) {
        try {
            // 进行jwt验证
            TokenEntity entity = tokenManager.getToken(token);
            ErrorCodeEnum errorCodeEnum = tokenManager.checkToken(entity);
            if (ErrorCodeEnum.SC0 == errorCodeEnum) {
                return entity.getAccount();
            } else {
                throw new ApiException(errorCodeEnum);
            }
        } catch (ApiException e) {
            throw e;
        } catch (ExpiredJwtException ee) {
            throw new ApiException(ErrorCodeEnum.TK1005);
        } catch (Exception e) {
            throw new ApiException(ErrorCodeEnum.TK1006);
        }
    }

    @Override
    public void destroy() {

    }
}